#pragma once
#ifndef _G_BIT_CONTAINER_H_
#define _G_BIT_CONTAINER_H_

#include "GTypes.h"

namespace GUtil
{
	template <class T>
	class GBitContainer
	{
	public:
		T Bits;

		GBitContainer()
		{
			Bits = (T)0;
		}

		GBitContainer(T Value)
		{
			Bits = Value;
		}

		~GBitContainer()
		{
		}
		
		operator T ()
		{
			return Bits;
		}

		operator const T () const
		{
			return Bits;
		}

		T CountBits() const
		{
			T Count = (T)0;	
			for (T Val = Bits; Val != 0; Val >>= 1)
			{
				if ((Val & 0x1) == 0x1)
				{
					Count++;
				}
			}

			return Count;
		}

		void SetBits(T Value)
		{
			Bits = Value;
		}

		T GetBits() const
		{
			return Bits;
		}
		
		bool Contains(T Value) const
		{
			return (Bits & Value) == Value;
		}

		bool GetBit(GUInt32 Index) const
		{
			return Bits & (0x1 << Index) != 0;
		}

		void RaiseAll()
		{
			Bits = ~(T)0;
		}

		void LowerAll()
		{
			Bits = (T)0;
		}

		void RaiseBits(T Value)
		{
			Bits |= Value;
		}
		void LowerBits(T Value)
		{
			Bits &= ~Value;
		}

		void RaiseBit(GUInt32 Index)
		{
			Bits |= (0x1 << Index);
		}

		void LowerBit(GUInt32 Index)
		{
			Bits &= ~(0x1 << Index);
		}

		bool operator () (GUInt32 Index)
		{
			return Bits & (0x1 << Index) != 0;
		}

		bool operator () (GUInt32 Index) const
		{
			return Bits & (0x1 << Index) != 0;
		}

		GBitContainer<T>& operator = (const T& Other)
		{
			Bits = Other;
			return *this;
		}

		GBitContainer<T>& operator &= (const T& Other)
		{
			Bits &= Other;
			return *this;
		}

		GBitContainer<T>& operator |= (const T& Other)
		{
			Bits |= Other;
			return *this;
		}

		GBitContainer<T>& operator ^= (const T& Other)
		{
			Bits ^= Other;
			return *this;
		}

		GBitContainer<T>& operator *= (const T& Other)
		{
			Bits *= Other;
			return *this;
		}

		GBitContainer<T>& operator /= (const T& Other)
		{
			Bits /= Other;
			return *this;
		}

		GBitContainer<T> operator ~ () const
		{
			return GBitContainer<T>(~Bits);
		}
						 
		GBitContainer<T> operator & (const T& Other) const
		{
			return GBitContainer<T>(Bits & Other);
		}
		
		GBitContainer<T> operator | (const T& Other) const
		{
			return GBitContainer<T>(Bits | Other);
		}
		
		GBitContainer<T> operator ^ (const T& Other) const
		{
			return GBitContainer<T>(Bits ^ Other);
		}
		
		GBitContainer<T> operator * (const T& Other) const
		{
			return GBitContainer<T>(Bits * Other);
		}
		
		GBitContainer<T> operator / (const T& Other) const
		{
			return GBitContainer<T>(Bits / Other);
		}
						 
		bool operator == (const T& Other) const
		{
			return Bits == Other;
		}
		
		bool operator != (const T& Other) const
		{
			return Bits != Other;
		}
		

	};

	typedef GBitContainer<GUInt32> GFlag;
	typedef GBitContainer<GUInt32> GMask;

}

#endif // _G_BIT_CONTAINER_H_